package cn.com.oceansoft.application.config;

import cn.com.oceansoft.application.interceptor.SessionInterceptor;
import cn.com.oceansoft.framework.resolver.AjaxMapperExceptionResolver;
import cn.com.oceansoft.framework.resolver.UcoxMappingExceptionResolver;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import static com.alibaba.fastjson.serializer.SerializerFeature.*;

/**
 * SpringMVC配置
 *
 * @author chenw
 * @create 16/2/4 01:00
 * @email javacspring@gmail.com
 */
//@EnableWebMvc
//@Configuration
//@Import({AppConfig.class})
//@PropertySource(name = "view", value = "classpath:properties/view.properties")
//@ComponentScan(
//        basePackages = "cn.com.oceansoft.modules.**.controller",
//        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class ControllerConfig extends WebMvcConfigurerAdapter {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private static final int maxUploadSizeInMb = 5 * 1024 * 1024; // 5 MB

    @Resource
    Environment environment;

//    private ApplicationContext applicationContext;

    @Value("${view.debug}")
    private String viewDebug;

    @Value("${view.js.version}")
    private String jsVersion;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
//        registry.addResourceHandler("/res/js/" + environment.getProperty("view.js.version") + "/**").addResourceLocations("/resource/js/").setCachePeriod(24 * 3600 * 7);
//        registry.addResourceHandler("/res/img").addResourceLocations("/resource/images/").setCachePeriod(24 * 3600 * 180);
        registry.addResourceHandler("/resource/**").addResourceLocations("/resource/").setCachePeriod(24 * 3600 * 7);
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addStatusController("error/403", HttpStatus.FORBIDDEN);
        registry.addStatusController("error/404", HttpStatus.NOT_FOUND);
        registry.addStatusController("error/405", HttpStatus.METHOD_NOT_ALLOWED);
        registry.addStatusController("error/500", HttpStatus.INTERNAL_SERVER_ERROR);
        registry.addRedirectViewController("/", "admin/login");
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(ucoxMappingExceptionResolver());
//        exceptionResolvers.add();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SessionInterceptor()).addPathPatterns("/**").excludePathPatterns("/api/**,/log/**");
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true)
                .favorParameter(false)
                .favorPathExtension(false)
                .ignoreAcceptHeader(false)
                .ignoreUnknownPathExtensions(true)
                .useJaf(true)
                .defaultContentTypeStrategy(contentNegotiationManager())
                .mediaType("json", MediaType.APPLICATION_JSON)
//                .mediaType("json", MediaType.APPLICATION_JSON_UTF8)
                .mediaType("xml", MediaType.APPLICATION_XML);
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(true, fastJsonJsonView());
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new FastJsonHttpMessageConverter());
//        converters.add(new SecurityFormDataConverter());
//        converters.add(new MapFormConverter());
    }

    @Bean
    public UcoxMappingExceptionResolver ucoxMappingExceptionResolver() {
        UcoxMappingExceptionResolver resolver = new UcoxMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.put("java.lang.Exception", "error/500");
        mappings.put("org.springframework.web.HttpRequestMethodNotSupportedException", "error/405");
        mappings.put("org.springframework.web.servlet.NoHandlerFoundException", "error/404");
        resolver.setExceptionMappings(mappings);
        resolver.setExceptionAttribute("exception");
        resolver.setDefaultStatusCode(500);
        resolver.setDefaultErrorView("error/500");
        resolver.setOrder(0);
        return resolver;
    }

    @Bean
    public AjaxMapperExceptionResolver ajaxMapperExceptionResolver() {
        return new AjaxMapperExceptionResolver();
    }


    @Bean(name = "filterMultipartResolver")
    public CommonsMultipartResolver filterMultipartResolver() {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(maxUploadSizeInMb);
        return commonsMultipartResolver;
    }

    @Bean
    public FastJsonJsonView fastJsonJsonView() {
        FastJsonJsonView fastJsonJsonView = new FastJsonJsonView();
        fastJsonJsonView.setUpdateContentLength(true);
        fastJsonJsonView.setContentType("application/json");
        fastJsonJsonView.setCharset(Charset.forName("UTF-8"));
        fastJsonJsonView.setFeatures(WriteMapNullValue, WriteNullStringAsEmpty, WriteDateUseDateFormat, SkipTransientField);
        return fastJsonJsonView;
    }

    @Bean
    public ContentNegotiationManager contentNegotiationManager() {
        Map<String, MediaType> pathExtensionStrategy = new HashMap<String, MediaType>() {{
//            put("json", MediaType.APPLICATION_JSON_UTF8);
            put("json", MediaType.APPLICATION_JSON);
            put("xml", MediaType.APPLICATION_XML);
            put("api", new MediaType("application", "ucox-api"));
        }};
        ContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy(pathExtensionStrategy);
        ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(strategy);
        return contentNegotiationManager;
    }
}
